import numpy
import scipy.special
import matplotlib.pyplot
%matplotlib inline

#神经网络
class NeuralNetwork :
    
    #初始化
    def __init__( self, input_nodes, hidden_nodes, output_nodes, learning_rate ) :
        self.i_nodes = input_nodes
        self.h_nodes = hidden_nodes
        self.o_nodes = output_nodes
        
        self.lr = learning_rate
        
        self.w_ih = numpy.random.normal( 0.0, pow(self.h_nodes, -0.5), (self.h_nodes, self.i_nodes) )
        self.w_ho = numpy.random.normal( 0.0, pow(self.o_nodes, -0.5), (self.o_nodes, self.h_nodes) )
        
        self.a_fun = lambda x : scipy.special.expit(x)
        pass
    
    #训练
    def train( self, input_list, target_list ) :
        inputs = numpy.array(input_list, ndmin = 2).T
        targets = numpy.array(target_list, ndmin = 2).T
        
        hidden_inputs = numpy.dot(self.w_ih, inputs)
        hidden_outputs = self.a_fun(hidden_inputs)
        
        final_inputs = numpy.dot(self.w_ho, hidden_outputs)
        final_outputs = self.a_fun(final_inputs)
        
        output_errors = targets - final_outputs
        hidden_errors = numpy.dot(self.w_ho.T, output_errors)
        
        self.w_ho += self.lr * numpy.dot((output_errors * final_outputs * ( 1.0 - final_outputs)), numpy.transpose(hidden_outputs))
        self.w_ih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs))
        
    #执行
    def query( self, input_list ) :
        # i to h
        start_input = numpy.array( input_list, ndmin = 2).T
        
        hidden_input = numpy.dot( self.w_ih, start_input )
        hidden_output = self.a_fun( hidden_input )
        
        # h to o
        final_input = numpy.dot( self.w_ho, hidden_output)
        final_output = self.a_fun( final_input )
        
        return final_output

def file_data( file_name ):
    file = open( file_name, "r" )
    lines = file.readlines()
    file.close()
    return lines

def auto_train( i_n, h_n, o_n, l_r, datas ):
    n = NeuralNetwork( i_n, h_n, o_n, l_r )

    for line in datas:
        data = line.split(',')
        inputs = ( numpy.asfarray( data[1:] ) / 255.0 * 0.99 ) + 0.01
        targes = numpy.zeros( o_n ) + 0.01
        targes[int( data[0] )] = 0.99
        n.train( inputs, targes )
    return n

def test_data( nn, dt ):
    data = dt.split(',')
    inputs = ( numpy.asfarray( data[1:] ) / 255.0 * 0.99 ) + 0.01
    result = nn.query( inputs )
    re = numpy.argmax(result, axis = 0)
    print('obj is ', dt[0])
    print('given is ', re[0])
    
input_nodes = 784
hidden_nodes = 100
output_nodes = 10

learning_rate = 0.3

datas = file_data( "100.csv" )

n = auto_train( input_nodes, hidden_nodes, output_nodes, learning_rate, datas)

ds = file_data("test.csv")
data = ds[0]
test_data( n, data )
